#include "SerialPort.h"

CSerialPort::CSerialPort()
{
    Comfd = 0;
}

CSerialPort::~CSerialPort()
{

}

//static
CSerialPort * CSerialPort::SerialPort = 0;

//函数名：
//函数功能:
//函数参数：
//返回值：
CSerialPort * CSerialPort::GetInstance()
{
    if(SerialPort == NULL)
    {
        SerialPort = new CSerialPort();
    }

    return SerialPort;
}


//函数名：ConnectSerialPort
//函数功能：打开串口
//函数参数：char *COM(in):端口号, int Speed(in):波特率, int DataBits(in)：数据位, int StopBit(in)：停止位, char Parity(in)：校验位
//返回值：正确打COM口返回true，否则返回false
bool CSerialPort::ConnectSerialPort(char *COM, int Speed, int DataBits, int StopBit, char Parity)
{
    int result;
    int speed_arr[8] = {B38400, B19200, B9600, B4800, B2400, B1200, B300};
    int name_arr[8] = {38400, 19200, 9600, 4800, 2400, 1200, 300};

    struct termios Opt;

    //open serial
    if((Comfd = open(COM, O_RDWR|O_NOCTTY)) == 0)
        return false;

    //set serial operation
    if((result = tcgetattr(Comfd, &Opt)) != 0)
        return false;

    tcflush(Comfd, TCIOFLUSH);

    for(unsigned int cur_num = 0; cur_num < sizeof(speed_arr)/sizeof(int); cur_num++)
    {
        if(Speed == name_arr[cur_num])
        {
            cfsetispeed(&Opt, speed_arr[cur_num]);
            cfsetospeed(&Opt, speed_arr[cur_num]);
            break;
        }
    }

    switch(DataBits)
    {
        case 7:
            Opt.c_cflag &= ~CSIZE;
            Opt.c_cflag |= CS7;
            break;

        case 8:
            Opt.c_cflag &= ~CSIZE;
            Opt.c_cflag |= CS8;
            break;

        default:
            return false;
    }

    switch(Parity)
    {
        case 'n':
        case 'N':
            Opt.c_cflag &= ~PARENB;
            Opt.c_iflag &= ~INPCK;
            break;

        case 'o':
        case 'O':
            Opt.c_cflag |= PARENB;
            Opt.c_cflag |= PARODD;
            Opt.c_iflag |= INPCK;
            break;

        case 'e':
        case 'E':
            Opt.c_cflag |= PARENB;
            Opt.c_cflag |= ~PARODD;
            Opt.c_iflag |= INPCK;
            break;

        case 's':
        case 'S':
            Opt.c_cflag &= ~PARENB;
            Opt.c_cflag &= ~CSTOPB;
            Opt.c_iflag |= INPCK;
            break;

        default:
            return false;
    }

    switch(StopBit)
    {
        case 1:
            Opt.c_cflag &= ~CSTOPB;
            break;

        case 2:
            Opt.c_cflag &= CSTOPB;
            break;

        default:
            return false;
    }

    Opt.c_cflag |= (CLOCAL|CREAD);
    Opt.c_lflag &= ~(ICANON|ECHO|ECHONL|ISIG);
    Opt.c_oflag &= ~(OPOST);
    Opt.c_oflag &= ~(ONLCR|OCRNL);   //将回车和换行当作同一个符号
    Opt.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
    Opt.c_cc[VTIME] = 10;
    Opt.c_cc[VMIN] = 0;

    tcflush(Comfd,TCIFLUSH);

    if(tcsetattr(Comfd, TCSANOW, &Opt) != 0)
        return false;

    return true;
}

//函数名：SendCommandToSerial
//函数功能：发送命令到串口
//函数参数：unsigned char * Command(in):命令参数
//返回值：正确发送命令返回true,否则返回false
bool CSerialPort::SendCommandToSerial(unsigned char * Command)
{
    memset(SendBuff, 0, BuffLen);
    for(int cur_num = 0; cur_num  < (Tool->StrlenUnsigned(Command)-1); cur_num += 2 )
    {
        SendBuff[cur_num/2] = 16 * Tool->ChartoInt(Command[cur_num]) + Tool->ChartoInt(Command[cur_num+1]);
    }
    if((m_DatLen = write(Comfd, SendBuff, (Tool->StrlenUnsigned(Command)/2))) <= 0)
    {
        return false;
    }
    return true;
}

//函数名：RecvDataFromSerial
//函数功能：从串口获取数据
//函数参数：char ** Data(out):返回获取到的数据
//返回值：返回获取到的字节数
int CSerialPort::RecvDataFromSerial(char **Data)
{
    int RecvLen;
    memset(RecvBuff, 0, BuffLen);
    *Data = new char[BuffLen];
    memset(*Data, 0, BuffLen);

    if((RecvLen = read(Comfd, RecvBuff, BuffLen))>0)
    {
        //cout << "RecvLen = " << RecvLen << endl;
        for(int cur_num = 0; cur_num < (RecvLen*2 - 1); cur_num += 2)
        {
                (*Data)[cur_num] = Tool->InttoChar(RecvBuff[cur_num/2]/16);
                (*Data)[cur_num+1] = Tool->InttoChar(RecvBuff[cur_num/2]%16);
        }
    }
    return RecvLen;
}

//函数名：CloseSerialPort
//函数功能：关闭串口
//函数参数：无
//返回值：无
void CSerialPort::CloseSerialPort()
{
    close(Comfd);
}

//函数名：Init
//函数功能：串口初始化
//函数参数：无
//返回值：正常初始化返回true，否则返回false
bool CSerialPort::Init()
{
    Tool = CTool::GetInstance();
    if(!Tool)
        return false;

    string ComArgument;
    int result;

    ifstream In;
    In.open(ComConfigur);
    if(!In.is_open())
        return false;
    while(getline(In, ComArgument))
    {
        string CurData(ComArgument.begin(), ComArgument.begin()+2);
        if(CurData == "##")
            continue;
        else if(ComArgument.length() != NULL)
            sscanf(ComArgument.c_str(), "%s %d %d %d %c", Com, &Speed, &DataBits, &StopBit, &Parity);
    }
   //cout << "Com:" << Com << " Speed:" << Speed << " DataBits:" << DataBits << " StopBit:" << StopBit << " Parity:" << Parity << endl;

    result = ConnectSerialPort(Com, Speed, DataBits,StopBit, Parity);
    if(!result)
        return false;

    CloseSerialPort();

    return true;
}

//函数名：Run
//函数功能：串口采集程序运行
//函数参数：unsigned char *Command(in):准备发送的命令, char *Data(out):接收到的数据
//返回值：正确返回收到数据的字节数，否则返回false
int CSerialPort::Run(const string & Command, string & Data)
{
    int result, byte = 0, times = 0;
    char *Datas;
    result = ConnectSerialPort(Com, Speed, DataBits,StopBit, Parity);
    if(!result)
        return false;

    while(byte <= 0)
    {
        result = SendCommandToSerial((unsigned char*)Command.c_str());
        if(!result)
            return false;

        usleep(700000);
        //usleep(500000);

        byte = RecvDataFromSerial(&Datas);
        times++;
        //cout << "byte = " << byte << endl;
        if (times >= 3) return false;
    }
    Data = Datas;
    //cout << "Data = " << Data << endl;
    return byte;
}

//函数名：Cleanup
//函数功能：串口类反初始化
//函数参数：无
//返回值：无
void CSerialPort::Cleanup()
{
    if(Comfd)
    {
        CloseSerialPort();
        Comfd = 0;
    }

    if(SerialPort)
    {
        delete SerialPort;
        SerialPort = 0;
    }
}
